package com.intercom;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.FileObserver;
import android.os.Handler;
import android.os.Message;

import com.intercom.MainActivity;
import com.intercom.Core;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

public class MainActivity extends Activity{

	public byte[] buffer;
	public static DatagramSocket socket;
	private int port = 50005;
	private AudioRecord recorder;
	private AudioTrack speaker;

	static final int SAMPLE_RATE = 8000;
	static final int SAMPLE_INTERVAL = 20; // milliseconds
	static final int SAMPLE_SIZE = 2; // bytes per sample
	static final int BUF_SIZE = SAMPLE_INTERVAL*SAMPLE_INTERVAL*SAMPLE_SIZE*2;
	String PATH_DNSMASQ = "";

	private boolean status = false;
	private boolean started = false;
	private boolean adhoc = false;
	private boolean bravo_dev = false;

	//	Variable for view fields
	private Spinner spConnectedDev;
	private Button bCreate;
	private Button bStartStop;
	private FileObserver fObserver;

	public static final String MSG_TAG = "TETHER -> NativeTask";
	public ArrayAdapter<String> adapter=null;
	private ProgressDialog pd;
	private Core app = null;
	private String inetAddr = "192.168.2.254";
	public static MainActivity currentInstance = null;

	private static void setCurrent(MainActivity current){
		MainActivity.currentInstance = current;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		bCreate = (Button)findViewById(R.id.create_btn);
		bStartStop = (Button)findViewById(R.id.button1);
		spConnectedDev = (Spinner)findViewById(R.id.connectedDev);

		this.app = (Core)this.getApplication();
		PATH_DNSMASQ = app.getApplicationContext().getApplicationContext().getFilesDir().getParent() + "/var/dnsmasq.leases";
		MainActivity.setCurrent(this); 

		if (Build.PRODUCT.equals("htc_bravo")) {
			bravo_dev = true;
			bCreate.setVisibility(View.VISIBLE);
			spConnectedDev.setVisibility(View.VISIBLE);
			findViewById(R.id.tvConnectedDev).setVisibility(View.VISIBLE);
			findViewById(R.id.button1).setEnabled(false);
		} else {
			bravo_dev = false;
			spConnectedDev.setVisibility(View.INVISIBLE);
			bCreate.setVisibility(View.INVISIBLE);
			findViewById(R.id.tvConnectedDev).setVisibility(View.INVISIBLE);
			findViewById(R.id.button1).setEnabled(true);
		}
	}

	private void startFileWatcher(String path) {
		adapter = new ArrayAdapter<String>(app.getApplicationContext(), android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		adapter.notifyDataSetChanged();

		runOnUiThread(new Runnable() {
			public void run() {
				spConnectedDev.setAdapter(adapter);
			}
		});

		fObserver = new FileObserver(path, FileObserver.CLOSE_WRITE | FileObserver.MODIFY) {

			@Override
			public void onEvent(int event, String path) {
				// TODO Auto-generated method stub
				Log.d(MSG_TAG,"File modyfied.");

				runOnUiThread(new Runnable() {
					public void run() {

						adapter.clear();
						for( String s : Utils.modified(PATH_DNSMASQ)) {
							adapter.add (s);
						}

						adapter.notifyDataSetChanged();
						Toast.makeText(app.getApplicationContext(),"Someone connected.", Toast.LENGTH_LONG).show();
					}
				});
			}
		};
		fObserver.startWatching();
	}

	private void stopFileWatcher() {
		fObserver.stopWatching();
	}

	public void startStreaming() {
		Thread streamThread = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
							AudioFormat.CHANNEL_CONFIGURATION_MONO,
							AudioFormat.ENCODING_PCM_16BIT) * 10;
					DatagramSocket socket = new DatagramSocket();
					Log.d("VS", "Socket Created.");
					Log.d("VS", "Min. buf size: " + minBufSize);

					byte[] buffer = new byte[BUF_SIZE];

					//					Log.d("VS","Buffer created of size " + minBufSize);
					DatagramPacket packet;

					final InetAddress destination = InetAddress.getByName(inetAddr);
					Log.d("VS", "Address retrieved");

					recorder= new AudioRecord(MediaRecorder.AudioSource.DEFAULT, SAMPLE_RATE,
							AudioFormat.CHANNEL_CONFIGURATION_MONO,
							AudioFormat.ENCODING_PCM_16BIT,
							minBufSize);
					Log.d("VS", "Recorder initialized");

					recorder.startRecording();

					while(status == true) {
						//reading data from MIC into buffer
						int bytes_read = recorder.read(buffer, 0, buffer.length);

						//putting buffer in the packet
						packet = new DatagramPacket (buffer,bytes_read,destination,port);
						socket.send(packet);
						Thread.sleep(SAMPLE_INTERVAL, 0);
					}

				} catch(UnknownHostException e) {
					Log.e("VS", "UnknownHostException");
				} catch (IOException e) {
					Log.e("VS", "IOException");
					//				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {
					if (socket!= null) {
						socket.close();
					}
				}

				if (socket!= null) {
					socket.close();
				}
			}
		});
		streamThread.start();
	}   
	public void startReceiving() {

		Thread receiveThread = new Thread (new Runnable() {

			@Override
			public void run() {

				try {

					DatagramSocket socket = new DatagramSocket(50005);
					Log.d("VR", "Socket Created");

					byte[] buf = new byte[BUF_SIZE];

					//					Log.d("VR", "Min buf size: " + minBufSize);

					speaker = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 
							SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
							AudioFormat.ENCODING_PCM_16BIT, BUF_SIZE, 
							AudioTrack.MODE_STREAM);

					speaker.play();

					while(status == true) {
						try {
							DatagramPacket packet = new DatagramPacket(buf,BUF_SIZE);
							socket.receive(packet);
							Log.d("VR", "Packet Received");

							//reading content from packet
							//							buffer=packet.getData();
							Log.d("VR", "Packet data read into buffer");

							//sending data to the Audiotrack obj i.e. speaker
							speaker.write(packet.getData(), 0, packet.getLength());
							Log.d("VR", "Writing buffer content to speaker");

						} catch(IOException e) {
							Log.e("VR","IOException");
						}
					}

				} catch (SocketException e) {
					Log.e("VR", "SocketException");
				} finally {
					if (socket!= null) {
						socket.close();
					}
				}
				if (socket!= null) {
					socket.close();
				}
			}
		});
		receiveThread.start();
	}

	public void onDestroy(){
		MainActivity.this.app.HelloWorld("Naraaaa");
		//    	MainActivity.this.app.stop();
		if (socket!= null) {
			socket.close();
		}
		super.onDestroy();
	}

	public void onCreateBtnClick(View v){
		if(!adhoc)
			pd = ProgressDialog.show(MainActivity.this, "Please wait", "Activating tether...", true,false);
		else
			pd = ProgressDialog.show(MainActivity.this, "Please wait", "Deactivating tether...", true,false);

		new Thread() {
			public void run() {
				try{
					if(!adhoc) {
						MainActivity.this.app.start();			
						startFileWatcher(PATH_DNSMASQ);
						adhoc = true;
						handler.sendEmptyMessage(0);
					} else {
						stopFileWatcher();
						//						adapter.clear();
						MainActivity.this.app.stop();
						adhoc = false;
						handler.sendEmptyMessage(1);
					}
				} catch (Exception e) {
					Log.e(MSG_TAG, e.getMessage());
				}
			}

			@SuppressLint("HandlerLeak")
			private Handler handler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					if(msg.what==0) {
						findViewById(R.id.button1).setEnabled(true);
						bCreate.setText("Disable network");
					}
					else {
						findViewById(R.id.button1).setEnabled(false);
						bCreate.setText("Enable network");
					}

					pd.dismiss();
				}
			};
		}.start();
	}

	public void onBtn_1Click(View v) {
		start_stop();
	}

	public void start_stop()
	{
		if (bravo_dev) {
			if(adapter!=null) {
				if(adapter.getCount() == 0 ) { 
					Toast.makeText(MainActivity.this,"No devices connected.", Toast.LENGTH_LONG).show();
					return;
				}
				else {
					inetAddr = spConnectedDev.getSelectedItem().toString().split(" - ")[1];
					Log.d(MSG_TAG,inetAddr);
				}		
			} else {
				Toast.makeText(MainActivity.this,"No devices connected.", Toast.LENGTH_LONG).show();
				return;
			}
		}

		if(!started) {
			started=true;
			status = true;
			startReceiving();
			startStreaming();
			bStartStop.setText("Stop");
		}
		else {
			started=false;
			status = false;
			recorder.release();
			speaker.release();
			bStartStop.setText("Start");
		}
	}

	public void onSendBtnClick(View v){
		//		MainActivity.this.app.HelloWorld("Send");
		//		if(!started) {
		//			started=true;
		//			status = true;
		//			startStreaming();
		//		} else {
		//			started=false;
		//			status = false;
		//			recorder.release();
		//		}
	}

	public void onReceiveBtnClick(View v){
		//		MainActivity.this.app.HelloWorld("Receive");
		//		if(!started) {
		//			started = true;
		//			status = true;
		//			startReceiving();
		//		}
		//		else {
		//			started=false;
		//			status = false;
		//			speaker.release();
		//		}
	}
}